using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Infrastructure.Upload;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System.ComponentModel.DataAnnotations;

namespace JGSY.CMS.LowCode.Platform.Controllers
{
    /// <summary>
    /// 文件上传管理控制器
    /// 提供完整的文件上传解决方案API，支持单文件上传、批量上传、分片上传等功能
    /// 集成本地存储和云存储(OSS)，支持图片处理、缩略图生成、文件类型验证等特性
    /// 提供文件管理、进度跟踪、断点续传等高级文件操作接口
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    [Authorize]
    public class FileUploadController : ControllerBase
    {
        /// <summary>
        /// 文件上传应用服务
        /// </summary>
        private readonly IFileUploadService _fileUploadService;
        
        /// <summary>
        /// 日志记录器
        /// </summary>
        private readonly ILogger<FileUploadController> _logger;
        
        /// <summary>
        /// 最大文件大小限制（100MB）
        /// </summary>
        private const long MaxFileSize = 100 * 1024 * 1024; // 100MB

        /// <summary>
        /// 初始化文件上传控制器实例
        /// </summary>
        /// <param name="fileUploadService">文件上传应用服务</param>
        /// <param name="logger">日志记录器</param>
        /// <exception cref="ArgumentNullException">当依赖项为null时抛出</exception>
        public FileUploadController(
            IFileUploadService fileUploadService,
            ILogger<FileUploadController> logger)
        {
            _fileUploadService = fileUploadService ?? throw new ArgumentNullException(nameof(fileUploadService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 单文件上传
        /// 支持单个文件的上传操作，包括文件验证、存储、缩略图生成等功能
        /// </summary>
        /// <param name="file">要上传的文件</param>
        /// <param name="folder">目标文件夹路径</param>
        /// <param name="generateThumbnail">是否生成缩略图（仅对图片有效）</param>
        /// <param name="category">文件分类</param>
        /// <returns>上传结果，包含文件URL、大小、类型等信息</returns>
        /// <response code="200">上传成功</response>
        /// <response code="400">请求参数错误或文件验证失败</response>
        /// <response code="413">文件大小超过限制</response>
        /// <response code="415">不支持的文件类型</response>
        [HttpPost("single")]
        [RequestSizeLimit(MaxFileSize)]
        public async Task<ActionResult<UploadResult>> UploadSingle(
            IFormFile file,
            [FromQuery] string? folder = null,
            [FromQuery] bool generateThumbnail = false,
            [FromQuery] string? category = null)
        {
            if (file == null || file.Length == 0)
            {
                return BadRequest(new { message = "请选择要上传的文件" });
            }

            if (file.Length > MaxFileSize)
            {
                return BadRequest(new { message = $"文件大小不能超过 {MaxFileSize / (1024 * 1024)}MB" });
            }

            try
            {
                var uploadRequest = new UploadRequest
                {
                    File = file,
                    Folder = folder,
                    GenerateThumbnail = generateThumbnail,
                    Category = category,
                    UserId = GetCurrentUserId()
                };

                var result = await _fileUploadService.UploadFileAsync(uploadRequest);
                return Ok(result);
            }
            catch (ArgumentException ex)
            {
                _logger.LogWarning(ex, "Invalid file upload request");
                return BadRequest(new { message = ex.Message });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error uploading file {FileName}", file.FileName);
                return StatusCode(500, new { message = "文件上传失败" });
            }
        }

        /// <summary>
        /// 多文件上传
        /// </summary>
        [HttpPost("multiple")]
        [RequestSizeLimit(MaxFileSize * 10)] // 10个文件的限制
        public async Task<ActionResult<MultipleUploadResult>> UploadMultiple(
            List<IFormFile> files,
            [FromQuery] string? folder = null,
            [FromQuery] bool generateThumbnail = false,
            [FromQuery] string? category = null)
        {
            if (files == null || !files.Any())
            {
                return BadRequest(new { message = "请选择要上传的文件" });
            }

            if (files.Count > 10)
            {
                return BadRequest(new { message = "单次最多只能上传10个文件" });
            }

            var totalSize = files.Sum(f => f.Length);
            if (totalSize > MaxFileSize * 10)
            {
                return BadRequest(new { message = $"文件总大小不能超过 {MaxFileSize * 10 / (1024 * 1024)}MB" });
            }

            try
            {
                var uploadRequests = files.Select(file => new UploadRequest
                {
                    File = file,
                    Folder = folder,
                    GenerateThumbnail = generateThumbnail,
                    Category = category,
                    UserId = GetCurrentUserId()
                }).ToList();

                var result = await _fileUploadService.UploadMultipleFilesAsync(uploadRequests);
                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error uploading multiple files");
                return StatusCode(500, new { message = "批量文件上传失败" });
            }
        }

        /// <summary>
        /// 分片上传初始化
        /// </summary>
        [HttpPost("chunk/init")]
        public async Task<ActionResult<ChunkUploadInitResult>> InitChunkUpload([FromBody] ChunkUploadInitRequest request)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                var result = await _fileUploadService.InitChunkUploadAsync(request);
                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error initializing chunk upload");
                return StatusCode(500, new { message = "分片上传初始化失败" });
            }
        }

        /// <summary>
        /// 上传文件分片
        /// </summary>
        [HttpPost("chunk/{uploadId}")]
        [RequestSizeLimit(10 * 1024 * 1024)] // 10MB per chunk
        public async Task<ActionResult<ChunkUploadResult>> UploadChunk(
            string uploadId,
            int chunkNumber,
            IFormFile chunk)
        {
            if (chunk == null || chunk.Length == 0)
            {
                return BadRequest(new { message = "分片数据不能为空" });
            }

            try
            {
                var request = new ChunkUploadRequest
                {
                    UploadId = uploadId,
                    ChunkNumber = chunkNumber,
                    ChunkData = chunk,
                    UserId = GetCurrentUserId()
                };

                var result = await _fileUploadService.UploadChunkAsync(request);
                return Ok(result);
            }
            catch (ArgumentException ex)
            {
                _logger.LogWarning(ex, "Invalid chunk upload request");
                return BadRequest(new { message = ex.Message });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error uploading chunk {ChunkNumber} for upload {UploadId}", chunkNumber, uploadId);
                return StatusCode(500, new { message = "分片上传失败" });
            }
        }

        /// <summary>
        /// 完成分片上传
        /// </summary>
        [HttpPost("chunk/{uploadId}/complete")]
        public async Task<ActionResult<UploadResult>> CompleteChunkUpload(string uploadId)
        {
            try
            {
                var result = await _fileUploadService.CompleteChunkUploadAsync(uploadId, GetCurrentUserId());
                return Ok(result);
            }
            catch (ArgumentException ex)
            {
                _logger.LogWarning(ex, "Invalid chunk upload completion request");
                return BadRequest(new { message = ex.Message });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error completing chunk upload {UploadId}", uploadId);
                return StatusCode(500, new { message = "完成分片上传失败" });
            }
        }

        /// <summary>
        /// 取消分片上传
        /// </summary>
        [HttpDelete("chunk/{uploadId}")]
        public async Task<ActionResult> CancelChunkUpload(string uploadId)
        {
            try
            {
                await _fileUploadService.CancelChunkUploadAsync(uploadId, GetCurrentUserId());
                return NoContent();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error canceling chunk upload {UploadId}", uploadId);
                return StatusCode(500, new { message = "取消分片上传失败" });
            }
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        [HttpDelete("{fileId}")]
        [Authorize(Policy = "file.delete")]
        public async Task<ActionResult> DeleteFile(string fileId)
        {
            try
            {
                var success = await _fileUploadService.DeleteFileAsync(fileId, GetCurrentUserId());
                if (!success)
                {
                    return NotFound(new { message = "文件不存在" });
                }
                return NoContent();
            }
            catch (UnauthorizedAccessException)
            {
                return Forbid();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting file {FileId}", fileId);
                return StatusCode(500, new { message = "删除文件失败" });
            }
        }

        /// <summary>
        /// 批量删除文件
        /// </summary>
        [HttpPost("batch-delete")]
        [Authorize(Policy = "file.delete")]
        public async Task<ActionResult<BatchDeleteResult>> BatchDeleteFiles([FromBody] JGSY.CMS.LowCode.Platform.Application.DTOs.BatchDeleteRequest request)
        {
            if (request?.FileIds == null || !request.FileIds.Any())
            {
                return BadRequest(new { message = "请提供要删除的文件ID" });
            }

            try
            {
                var result = await _fileUploadService.BatchDeleteFilesAsync(request.FileIds, GetCurrentUserId());
                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error batch deleting files");
                return StatusCode(500, new { message = "批量删除文件失败" });
            }
        }

        /// <summary>
        /// 获取文件信息
        /// </summary>
        [HttpGet("{fileId}")]
        public async Task<ActionResult<FileInfoData>> GetFileInfo(string fileId)
        {
            try
            {
                var fileInfo = await _fileUploadService.GetFileInfoAsync(fileId);
                if (fileInfo == null)
                {
                    return NotFound(new { message = "文件不存在" });
                }
                return Ok(fileInfo);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting file info {FileId}", fileId);
                return StatusCode(500, new { message = "获取文件信息失败" });
            }
        }

        /// <summary>
        /// 获取文件列表
        /// </summary>
        [HttpGet]
        public async Task<ActionResult<PagedResult<FileInfoData>>> GetFiles(
            [FromQuery] string? folder = null,
            [FromQuery] string? category = null,
            [FromQuery] string? fileType = null,
            [FromQuery] DateTime? uploadedAfter = null,
            [FromQuery] DateTime? uploadedBefore = null,
            [FromQuery] int page = 1,
            [FromQuery] int pageSize = 20)
        {
            try
            {
                var request = new GetFilesRequest
                {
                    Folder = folder,
                    Category = category,
                    FileType = fileType,
                    UploadedAfter = uploadedAfter,
                    UploadedBefore = uploadedBefore,
                    UserId = GetCurrentUserId(),
                    Page = page,
                    PageSize = pageSize
                };

                var result = await _fileUploadService.GetFilesAsync(request);
                return Ok(result);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting files list");
                return StatusCode(500, new { message = "获取文件列表失败" });
            }
        }

        /// <summary>
        /// 生成文件访问令牌（用于私有文件访问）
        /// </summary>
        [HttpPost("{fileId}/access-token")]
        public async Task<ActionResult<FileAccessTokenResult>> GenerateAccessToken(
            string fileId,
            [FromBody] GenerateAccessTokenRequest? request = null)
        {
            try
            {
                var expiresIn = request?.ExpiresInMinutes ?? 60; // 默认1小时
                var result = await _fileUploadService.GenerateAccessTokenAsync(fileId, GetCurrentUserId(), expiresIn);
                return Ok(result);
            }
            catch (ArgumentException ex)
            {
                _logger.LogWarning(ex, "Invalid access token generation request");
                return BadRequest(new { message = ex.Message });
            }
            catch (UnauthorizedAccessException)
            {
                return Forbid();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error generating access token for file {FileId}", fileId);
                return StatusCode(500, new { message = "生成访问令牌失败" });
            }
        }

        /// <summary>
        /// 获取上传进度（用于大文件上传）
        /// </summary>
        [HttpGet("progress/{uploadId}")]
        public async Task<ActionResult<UploadProgressResult>> GetUploadProgress(string uploadId)
        {
            try
            {
                var progress = await _fileUploadService.GetUploadProgressAsync(uploadId, GetCurrentUserId());
                if (progress == null)
                {
                    return NotFound(new { message = "上传记录不存在" });
                }
                return Ok(progress);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting upload progress {UploadId}", uploadId);
                return StatusCode(500, new { message = "获取上传进度失败" });
            }
        }

        /// <summary>
        /// 获取允许的文件类型
        /// </summary>
        [HttpGet("allowed-types")]
        [AllowAnonymous]
        public ActionResult<AllowedFileTypesResult> GetAllowedFileTypes()
        {
            var result = new AllowedFileTypesResult
            {
                Images = new[] { ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg" },
                Documents = new[] { ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".txt", ".rtf" },
                Videos = new[] { ".mp4", ".avi", ".mov", ".wmv", ".flv", ".webm" },
                Audio = new[] { ".mp3", ".wav", ".aac", ".ogg", ".m4a" },
                Archives = new[] { ".zip", ".rar", ".7z", ".tar", ".gz" },
                MaxFileSize = MaxFileSize
            };

            return Ok(result);
        }

        private int GetCurrentUserId()
        {
            var userIdClaim = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
            return int.TryParse(userIdClaim?.Value, out int userId) ? userId : 0;
        }
    }





 

 




   

 


   

 



   
}
